/*
 * Copyright (C) 2006 - 2025 Evan Teran <evan.teran@gmail.com>
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#ifndef ISTATE_H_20110315_
#define ISTATE_H_20110315_

#include "Register.h"
#include "Types.h"
#include <memory>

// TODO(eteran): This file is still too taylored to x86 and family
// we should develop a better abstraction model at some point

class IState {
public:
	virtual ~IState() = default;

public:
	[[nodiscard]] virtual std::unique_ptr<IState> clone() const = 0;

public:
	[[nodiscard]] virtual bool empty() const                            = 0;
	[[nodiscard]] virtual edb::address_t framePointer() const           = 0;
	[[nodiscard]] virtual edb::address_t instructionPointer() const     = 0;
	[[nodiscard]] virtual edb::address_t stackPointer() const           = 0;
	[[nodiscard]] virtual edb::reg_t debugRegister(size_t n) const      = 0;
	[[nodiscard]] virtual edb::reg_t flags() const                      = 0;
	[[nodiscard]] virtual QString flagsToString() const                 = 0;
	[[nodiscard]] virtual QString flagsToString(edb::reg_t flags) const = 0;
	[[nodiscard]] virtual Register flagsRegister() const                = 0;
	[[nodiscard]] virtual Register instructionPointerRegister() const   = 0;
	[[nodiscard]] virtual Register value(const QString &reg) const      = 0;
	virtual void adjustStack(int bytes)                                 = 0;
	virtual void clear()                                                = 0;
	virtual void setDebugRegister(size_t n, edb::reg_t value)           = 0;
	virtual void setFlags(edb::reg_t flags)                             = 0;
	virtual void setInstructionPointer(edb::address_t value)            = 0;
	virtual void setRegister(const QString &name, edb::reg_t value)     = 0;
	virtual void setRegister(const Register &reg)                       = 0;

public:
	// GP
	[[nodiscard]] virtual Register gpRegister(size_t n) const = 0;

public:
	// This is a more generic means to request architecture
	// specific registers. The type should be the result of
	// edb::string_hash, for example:
	// edb::string_hash("mmx"), string_hash("xmm"), and string_hash("ymm")
	// This will allow this interface to be much more platform independent
	[[nodiscard]] virtual Register archRegister(uint64_t type, size_t n) const = 0;

#if defined(EDB_X86) || defined(EDB_X86_64)
public:
	// FPU
	[[nodiscard]] virtual int fpuStackPointer() const                       = 0;
	[[nodiscard]] virtual bool fpuRegisterIsEmpty(std::size_t n) const      = 0;
	[[nodiscard]] virtual edb::value80 fpuRegister(size_t n) const          = 0;
	[[nodiscard]] virtual QString fpuRegisterTagString(std::size_t n) const = 0;
	[[nodiscard]] virtual edb::value16 fpuControlWord() const               = 0;
	[[nodiscard]] virtual edb::value16 fpuStatusWord() const                = 0;
	[[nodiscard]] virtual edb::value16 fpuTagWord() const                   = 0;
#endif
};

#endif
